package com.refusea.train.mapper

import com.refusea.train.domain.entity.ClassGroup
import com.refusea.train.domain.entity.Order
import com.refusea.train.domain.req.OrderReq
import org.apache.ibatis.annotations.Delete
import org.apache.ibatis.annotations.Insert
import org.apache.ibatis.annotations.Mapper
import org.apache.ibatis.annotations.Options
import org.apache.ibatis.annotations.Param
import org.apache.ibatis.annotations.Select
import org.apache.ibatis.annotations.Update
import java.time.LocalDate
import java.time.LocalDateTime

@Mapper
interface OrderMapper {

    @Insert(
        """
        INSERT INTO `order` (
            school_id, parent_id, student_id, course_id, paid, grouped, completed, amount
        ) VALUES (
            #{schoolId}, #{parentId}, #{studentId}, #{courseId}, #{paid}, 0, 0, #{amount}
        )
    """
    )
    @Options(useGeneratedKeys = true, keyProperty = "id")
    fun insert(order: Order): Int

    @Delete("DELETE FROM `order` WHERE id = #{id}")
    fun delete(id: Int): Int

    @Update(
        """
        UPDATE `order` SET 
            school_id = #{schoolId}, parent_id = #{parentId}, course_id = #{courseId}, 
            pay_status = #payStatus}, amount = #{amount}
        WHERE id = #{id}
    """
    )
    fun update(order: Order): Int

    @Select("SELECT * FROM `order` WHERE id = #{id}")
    fun select(id: Int): Order?

    @Select("SELECT * FROM `order`")
    fun list(): List<Order>


    @Select("<script>SELECT * FROM `order` WHERE $ORDER_CONDITION order by id desc limit #{offset}, #{limit}</script>")
    fun query(req: OrderReq): List<Order>

    @Select("<script>SELECT count(*) FROM `order` WHERE $ORDER_CONDITION</script>")
    fun count(req: OrderReq): Int

    @Update("UPDATE `order` SET paid = 1 WHERE id = #{id}")
    fun markPaid(@Param("id") id: Int): Int

    @Select("SELECT * FROM `order` WHERE school_id = #{schoolId} and course_id = #{courseId} and student_id = #{studentId}")
    fun selectByCourseIdAndStudentId(
        @Param("schoolId") schoolId: Int,
        @Param("courseId") courseId: Int,
        @Param("studentId") studentId: Int,
    ): List<Order>

    @Select(
        """
            SELECT student_id FROM `order` 
            WHERE school_id=#{schoolId} and course_id=#{courseId} 
            and paid=1 and grouped=0
        """
    )
    fun ungroupedStudents(@Param("schoolId") schoolId: Int, @Param("courseId") courseId: Int): List<Int>

    @Update(
        """
        <script>
        UPDATE `order` SET grouped = 1 
        WHERE school_id = #{schoolId} and course_id = #{courseId} and student_id in
        <foreach collection="studentIds" item="sid" separator="," open="(" close=")">
            #{sid}
        </foreach>
        and paid = 1 and completed = 0
        </script>
        """
    )
    fun markGrouped(classGroup: ClassGroup): Int

    @Update(
        """
        <script>
        UPDATE `order` SET study_status = 'PENDING' 
        WHERE school_id = #{schoolId} and course_id = #{courseId} and student_id in
        <foreach collection="studentIds" item="sid" separator="," open="(" close=")">
            #{sid}
        </foreach>
        and pay_status = 'PAID' and study_status='STUDYING'
        </script>
        """
    )
    fun deactivate(classGroup: ClassGroup): Int

    @Update(
        """
        <script>
        UPDATE `order` SET study_status = 'COMPLETED' 
        WHERE school_id = #{schoolId} and course_id = #{courseId} and student_id in
        <foreach collection="studentIds" item="sid" separator="," open="(" close=")">
            #{sid}
        </foreach>
        and pay_status = 'PAID' and study_status='STUDYING'
        </script>
        """
    )
    fun completed(
        @Param("schoolId") schoolId: Int,
        @Param("courseId") courseId: Int,
        @Param("studentIds") studentIds: List<Int>,
    ): Int

    @Select(
        """
        <script>
        SELECT * FROM `order` where 
        parent_id in
        <foreach collection="userIds" item="uid" separator="," open="(" close=")">
            #{uid}
        </foreach>
        <if test='start!=null'>and pt > #{start}</if>
        and pt &lt;= #{end}
        and paid=1
        </script>
        """
    )
    fun listByUsers(
        @Param("userIds") userIds: List<Int>,
        @Param("start") start: LocalDateTime?,
        @Param("end") end: LocalDate,
    ): List<Order>

    companion object {
        const val ORDER_CONDITION = """
        school_id = #{schoolId}
        <if test='start!=null'>and ct >= #{start}</if>
        <if test='end!=null'>and ct &lt; #{end}</if>
        <if test='parentId!=null and parentId!=0'>and parent_id = #{parentId}</if>
        <if test='studentId!=null and studentId!=0'>and student_id = #{studentId}</if>
        <if test='courseId!=null and courseId!=0'>and course_id = #{courseId}</if>
        <if test='paid!=null'>and paid=#{paid}</if>
        <if test='grouped!=null'>and grouped=#{grouped}</if>
        <if test='completed!=null'>and completed=#{completed}</if>
        """
    }
}

